package it.yuzuojian.com.controller;


import com.fasterxml.jackson.databind.ObjectMapper;

import it.yuzuojian.com.pojo.Keyboard;
import it.yuzuojian.com.pojo.Monitor;
import it.yuzuojian.com.pojo.Mouse;
import it.yuzuojian.com.task.ScreenCaptureTask;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.concurrent.*;
import java.util.logging.Logger;


/**
 * @author yzj
 */
@Component
@ServerEndpoint(value = "/webSocket")
public class WebSocketServerController {

    private static ObjectMapper objectMapper = new ObjectMapper();

    private  static ConcurrentHashMap<String, Session> sessionConcurrentHashMap= new ConcurrentHashMap<>();

    private Logger logger = Logger.getLogger("WebSocketServerController");

    private Robot robot = new Robot();
    private ExecutorService executorService = new ThreadPoolExecutor(4,
            10,
            3,
            TimeUnit.SECONDS,
            new SynchronousQueue<>(),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    public WebSocketServerController() throws AWTException {
    }


    @OnOpen
    public void OnOpen(Session session) throws IOException, AWTException, EncodeException {
        if(sessionConcurrentHashMap.get(session.getId())==null){
            sessionConcurrentHashMap.put(session.getId(),session);
            ScreenCaptureTask screenCaptureTask = new ScreenCaptureTask(session);
            executorService.execute(screenCaptureTask);
        }

    }

    @OnClose
    public void OnClose(Session session) throws IOException {
        sessionConcurrentHashMap.remove(session.getId());

    }

    @OnError
    public void OnError(Throwable throwable) throws IOException {

    }


    @OnMessage
    public void onMessage(Session session, String message) throws IOException {
        //键盘监听事件
        Monitor monitor = objectMapper.readValue(message, Monitor.class);
        Keyboard keyboard = monitor.getKeyboard();
        Mouse mouse = monitor.getMouse();
        try {
            if (keyboard != null) {
                if ("onkeyup".equals(keyboard.getType())) {
                    robot.keyRelease(keyCodeEncode(keyboard.getKeyCode()));
                    robot.delay(200);
                } else {
                    robot.keyPress(keyCodeEncode(keyboard.getKeyCode()));
                }
            }
        }catch (Exception e){
            logger.info(e.getMessage()+"-----暂不支持此按键--->"+keyboard.getKeyCode()+"-"+keyboard.getCode());
        }


        if (mouse != null) {
            switch (mouse.getType()) {
                case "onmousedown":
                    if(mouse.getButton()==2){
                        //处理右键事件，左键事件采用前台html判断的单击和双击  滑轮通过滑轮监控事件处理
                        robot.mousePress(InputEvent.BUTTON3_MASK);
                    }else if (mouse.getButton()==0){
                        robot.mousePress(InputEvent.BUTTON1_MASK);
                    }

                    break;
                case "onmouseup":
                    if(mouse.getButton()==2){
                        //处理右键事件，左键事件采用前台html判断的单击和双击  滑轮通过滑轮监控事件处理
                        robot.mouseRelease(InputEvent.BUTTON3_MASK);
                    }else if (mouse.getButton()==0){
                        robot.mouseRelease(InputEvent.BUTTON1_MASK);
                    }
                    break;
                case "onmousemove":
                    //Point location = MouseInfo.getPointerInfo().getLocation();
                    robot.mouseMove( mouse.getMovementX(),  mouse.getMovementY());

                    break;
                case "wheelDelta":

                    robot.mouseWheel(-(mouse.getWheelDeltaX()!=0 ? mouse.getWheelDeltaX()/10 : mouse.getWheelDeltaY()/10));
                    break;
                case "ondblclick":
                    robot.mousePress(InputEvent.BUTTON1_MASK);
                    robot.mouseRelease(InputEvent.BUTTON1_MASK);
                    robot.mousePress(InputEvent.BUTTON1_MASK);
                    robot.mouseRelease(InputEvent.BUTTON1_MASK);
                    break;
                default:
                    break;
            }
        }

    }

    /**
     * 前台js 键盘时间code和KeyValue 对应关系
     * @param keyCode
     * @return
     */
    public int keyCodeEncode(int keyCode){//有空再补吧，根据test包下自己手敲，太恶心了-yzj
        switch (keyCode) {
            case 8:
                return KeyEvent.VK_BACK_SPACE;
            case 91://win
                return 524;
            case 9:
                return KeyEvent.VK_TAB;
            case 13:
                return KeyEvent.VK_ENTER;
            case 186:
                return 59;
            case 187:
                return 61;
            case 190:
                return 46;
            case 191:
                return 47;
            case 220:
                return 92;
            case 219:
                return 91;
            case 188:
                return 44;
            case 175:
                return 0;
            case 189:
                return 45;
            case 174:
                return 93;
            default:
                return keyCode;
        }
    }


}
